﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ModelBase.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the ModelBase type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Client.Model
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;

    /// <summary>
    /// Defines the <seealso cref="ModelBase"/> type.
    /// </summary>
    public class ModelBase : INotifyPropertyChanged, INotifyPropertyChanging
    {
        /// <summary>
        /// Member variable _dirty
        /// </summary>
        private bool _dirty;

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Occurs when a property value is changing.
        /// </summary>
        public event PropertyChangingEventHandler PropertyChanging;

        #region Administrative Properties

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="ModelBase"/> is dirty.
        /// </summary>
        /// <value>
        ///   <c>true</c> if dirty; otherwise, <c>false</c>.
        /// </value>
        public bool Dirty
        {
            get
            {
                return _dirty;
            }

            set
            {
                _dirty = value;
                RaisePropertyChangedEvent("Dirty");
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [ignore property change events].
        /// </summary>
        /// <value>
        /// <c>true</c> if [ignore property change events]; otherwise, <c>false</c>.
        /// </value>
        internal virtual bool IgnorePropertyChangeEvents { get; set; }

        #endregion Administrative Properties

        /// <summary>
        /// Gets a value indicating whether [throw on invalid property name].
        /// </summary>
        /// <value>
        /// true if [throw on invalid property name]; otherwise, false.
        /// </value>
        protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

        /// <summary>
        /// Verifies the name of the property.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        [DebuggerStepThrough]
        public void VerifyPropertyName(string propertyName)
        {
            if (TypeDescriptor.GetProperties(this)[propertyName] == null)
            {
                var msg = "Invalid property name: " + propertyName;

                if (ThrowOnInvalidPropertyName)
                {
                    throw new Exception(msg);
                }
            }
        }

        /// <summary>
        /// Raises the PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The name of the changed property.</param>
        public virtual void RaisePropertyChangedEvent(string propertyName)
        {
            if (IgnorePropertyChangeEvents)
            {
                return;
            }

            if (PropertyChanged == null)
            {
                return;
            }

            var e = new PropertyChangedEventArgs(propertyName);
            PropertyChanged(this, e);
        }

        /// <summary>
        /// Raises the PropertyChanging event.
        /// </summary>
        /// <param name="propertyName">The name of the changing property.</param>
        public virtual void RaisePropertyChangingEvent(string propertyName)
        {
            if (IgnorePropertyChangeEvents)
            {
                return;
            }

            if (PropertyChanging == null)
            {
                return;
            }

            var e = new PropertyChangingEventArgs(propertyName);
            PropertyChanging(this, e);
        }
    }
}